package com.ruoyi.erp.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.erp.domain.*;
import com.ruoyi.erp.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.erp.mapper.BillSettleMapper;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

/**
 * 外派结算Service业务层处理
 * 
 * @author sauger
 * @date 2022-03-24
 */
@Service
public class BillSettleServiceImpl implements IBillSettleService 
{
    @Autowired
    private BillSettleMapper billSettleMapper;
    @Autowired
    private IStaffingMonthBillService staffingMonthBillService;
    @Autowired
    private IBillSettleDetailService detailService;
    @Autowired
    private IStaffingPoService poService;
    @Autowired
    private IReceivablePlanService receivablePlanService;
    @Autowired
    private IProjectService projectService;

    /**
     * 查询外派结算
     * 
     * @param id 外派结算主键
     * @return 外派结算
     */
    @Override
    public BillSettle selectBillSettleById(Integer id)
    {
        return billSettleMapper.selectBillSettleById(id);
    }

    /**
     * 查询外派结算列表
     * 
     * @param billSettle 外派结算
     * @return 外派结算
     */
    @Override
    public List<BillSettle> selectBillSettleList(BillSettle billSettle)
    {
        List<BillSettle> settles = billSettleMapper.selectBillSettleList(billSettle);
        if (settles.size() == 1 && StringUtils.isNull(settles.get(0))){
            return new ArrayList<>();
        }else
        {
            return settles;
        }
    }

    /**
     * 查询外派结算列表
     *
     * @param billSettle
     * @param withDetail 同时查询bills和po信息
     * @return
     */
    @Override
    public List<BillSettle> selectBillSettleList(BillSettle billSettle, Boolean withDetail) {
        List<BillSettle> settles = this.selectBillSettleList(billSettle);
        settles.forEach(billSettle1 -> {
            billSettle1.setMonthBills(detailService.selectSettleMonthBillBySettleId(billSettle1.getId()));
        });

        return settles;
    }

    /**
     * 新增外派结算
     * 
     * @param billSettle 外派结算
     * @return 结果
     */
    @Override
    @Transactional
    public int insertBillSettle(BillSettle billSettle)
    {



        //处理bill
        billSettle.setCreateTime(DateUtils.getNowDate());
        int iRet = billSettleMapper.insertBillSettle(billSettle);
        billSettle.getMonthBills().forEach((bill) -> {
            detailService.insertSettleBillMonthBill(billSettle.getId(), bill);
        });
        if (!StringUtils.isNull(billSettle.getSettlePos())){
            billSettle.getSettlePos().stream().filter(f -> f.getAmount().compareTo(BigDecimal.ZERO) == 1).forEach(po -> {
                detailService.insertSettleBillPo(billSettle.getId(), po);
            });
        }
        //插入到收款计划中
        ReceivablePlan receivablePlan = new ReceivablePlan();
        receivablePlan.setCreateTime(DateUtils.getNowDate());
        receivablePlan.setPlanStatus("expect");
        receivablePlan.setPlanType("staffing");
        receivablePlan.setPlanNumber("1000");
        receivablePlan.setInvoiceStatus("N");
        receivablePlan.setPayedAmount(BigDecimal.ZERO);
        receivablePlan.setCognizanceType("receivable");
        receivablePlan.setCustomerId(billSettle.getCustomerId());
        receivablePlan.setCognizanceDate(DateUtils.getNowDate());
        receivablePlan.setProjectId(billSettle.getId());
        BigDecimal totalAmount = billSettle.getMonthBills().stream().map(m -> m.getAmount()).reduce(BigDecimal.ZERO,BigDecimal::add);
        receivablePlan.setExpectAmount(totalAmount);
        //取第一个账单项目的事业部
        Project project = projectService.selectProjectById(billSettle.getMonthBills().get(0).getProjectId());
        receivablePlan.setBusinessUnitId(project.getBusinessUnitId());
        receivablePlanService.insertReceivablePlan(receivablePlan);
        return iRet;
    }

    /**
     * 修改外派结算
     * 
     * @param billSettle 外派结算
     * @return 结果
     */
    @Override
    @Transactional
    public int updateBillSettle(BillSettle billSettle)
    {
        Integer settleId = billSettle.getId();
        //从数据中载入已有数据
        BillSettle exist = this.selectBillSettleById(billSettle.getId());
        this.loadDetails(exist);
        List<SettleMonthBill> existBills = exist.getMonthBills();
        List<SettleMonthBill> passBills = billSettle.getMonthBills();

        //处理新增bills
        List<SettleMonthBill> insertBills = passBills.stream().filter(getBill -> StringUtils.isNull(getBill.getSettleDetailId())).collect(Collectors.toList());
        List<SettleMonthBill> deleteBills = existBills.stream().filter(f -> !passBills.stream().map(m -> m.getSettleDetailId()).collect(Collectors.toList()).contains(f.getSettleDetailId())).collect(Collectors.toList());
        List<SettleMonthBill> updateBills = passBills.stream().filter(f -> !StringUtils.isNull(f.getSettleDetailId())).collect(Collectors.toList());
        insertBills.forEach(item -> detailService.insertSettleBillMonthBill(settleId, item));
        //处理删除的bill
        deleteBills.forEach(item -> detailService.deleteSettleBillMonthBill(item));
        //更新bills
        updateBills.forEach(item -> {
            detailService.updateSetlleBillMonthBill(item);
        });

        List<SettlePo> existPos = exist.getSettlePos();
        List<SettlePo> passPos = billSettle.getSettlePos();

        //处理新增Po
        passPos.stream().filter(passPo -> StringUtils.isNull(passPo.getSettleDetailId()) && passPo.getAmount().compareTo(BigDecimal.ZERO) != 0)
                .forEach(item -> detailService.insertSettleBillPo(settleId, item));
        //处理删除的po
        existPos.stream().filter(f -> !passPos.stream().map(m -> m.getSettleDetailId()).collect(Collectors.toList()).contains(f.getSettleDetailId()))
                .forEach(item -> detailService.deleteSettleBillPo(item));
        //更新po
        passPos.stream().filter(f -> !StringUtils.isNull(f.getSettleDetailId())).forEach(item -> {
            detailService.updateSettleBillPo(existPos.stream().filter( f -> f.getSettleDetailId().equals(item.getSettleDetailId())).findFirst().get(), item);
        });

        //        //处理应收金额

        BillSettle updatedBill = this.selectBillSettleById(billSettle.getId());
        ReceivablePlan search = new ReceivablePlan();
        search.setPlanType("staffing");
        search.setProjectId(updatedBill.getId());
        List<ReceivablePlan> plans = receivablePlanService.selectReceivablePlanList(search);
        if (!StringUtils.isNull(plans) && plans.size() > 0)
        {
            plans.get(0).setExpectAmount(updatedBill.getAmount());
            receivablePlanService.updateReceivablePlan(plans.get(0));
        }

        billSettle.setUpdateTime(DateUtils.getNowDate());
        return billSettleMapper.updateBillSettle(billSettle);
    }

    /**
     * 批量删除外派结算
     * 
     * @param ids 需要删除的外派结算主键
     * @return 结果
     */
    @Override
    public int deleteBillSettleByIds(String ids)
    {
        return billSettleMapper.deleteBillSettleByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除外派结算信息
     * 
     * @param id 外派结算主键
     * @return 结果
     */
    @Override
    public int deleteBillSettleById(Integer id)
    {
        BillSettle billSettle = this.selectBillSettleById(id);
        if (!StringUtils.isNull(billSettle.getPayedAmount()) && billSettle.getPayedAmount().compareTo(BigDecimal.ZERO) == 1)
        {
            throw new ServiceException("结算已有收款，不能删除");
        }
        this.loadDetails(billSettle);
        //修改回退monthBill的结算金额
        if (!StringUtils.isNull(billSettle.getMonthBills())){
            billSettle.getMonthBills().stream().forEach(item ->{
              detailService.deleteSettleBillMonthBill(item);
            });
        }
        //回退po的结算金额
        if (!StringUtils.isNull(billSettle.getSettlePos()))
        {
            billSettle.getSettlePos().stream().forEach(item -> {
                detailService.deleteSettleBillPo(item);
            });
        }
        //删除应收
        ReceivablePlan search = new ReceivablePlan();
        search.setProjectId(id);
        search.setPlanType("staffing");
        List<ReceivablePlan> plans = receivablePlanService.selectReceivablePlanList(search);
        if(!StringUtils.isNull(plans) && plans.size()>0){
            Integer deleteId = plans.get(0).getId();
            receivablePlanService.deleteReceivablePlanById(deleteId);
        }
        return billSettleMapper.deleteBillSettleById(id);
    }

    /**
     * 载入结算的账单详情和po详情
     *
     * @param billSettle
     */
    @Override
    public BillSettle loadDetails(BillSettle billSettle) {
        if (!StringUtils.isNull(billSettle)) {
            billSettle.setMonthBills(detailService.selectSettleMonthBillBySettleId(billSettle.getId()));
            billSettle.setSettlePos(detailService.selectSettlePoBySettleId(billSettle.getId()));
        }
        return billSettle;

    }

    /**
     * 载入结算的账单详情和po详情
     *
     * @param billSettles
     */
    @Override
    public List<BillSettle> loadDetails(List<BillSettle> billSettles) {
        if (!StringUtils.isNull(billSettles)){
            billSettles.forEach(billSettle -> {
                this.loadDetails(billSettle);
            });
        }
        return billSettles;
    }
}
